package net.aiion.weave.impl.painters;

import java.util.Collection;
import java.util.Iterator;

import net.aiion.weave.spi.naming.Context;
import net.aiion.weave.spi.painters.PaintBrush;
import net.aiion.weave.spi.painters.PaintContext;
import net.aiion.weave.spi.painters.Painter;

public class PaintContextImpl implements PaintContext
{
    private final Iterator<Painter> paintersIterator;

    private final Context namingContext;
    private final PaintBrush brush;
    private final Object named;

    public PaintContextImpl(final Collection<Painter> aPainters, final Context aNamingContext, final Object aNamed,
        final PaintBrush aBrush)
    {
        paintersIterator = aPainters.iterator();
        namingContext = aNamingContext;
        brush = aBrush;
        named = aNamed;
    }

    @Override
    public Context getContext() {
        return namingContext;
    }

    @Override
    public Object getComponent() {
        return named;
    }

    @Override
    public <T> T getComponent(final Class<T> aClass) {
        if (aClass.isInstance(named)) {
            return aClass.cast(named);
        }

        throw new ProceedPaintingException();
    }

    @Override
    public PaintBrush getPaintBrush() {
        return brush;
    }

    @Override
    public <T extends PaintBrush> T getPaintBrush(final Class<T> aClass) {
        if (aClass.isInstance(brush)) {
            return aClass.cast(brush);
        }

        throw new ProceedPaintingException();
    }

    @Override
    public PaintBrush forwardPaint() {
        if (paintersIterator.hasNext()) {
            try {
                return paintersIterator.next().paintComponent(this);
            } catch (final ProceedPaintingException e) {
                return forwardPaint();
            }
        }

        return null;
    }

    private static class ProceedPaintingException extends RuntimeException
    {
        private static final long serialVersionUID = 358086311545122457L;

        public ProceedPaintingException() {
        }
    }
}
